package com.example.novelspringbootmysql.controller;
import com.example.novelspringbootmysql.entity.*;
import com.example.novelspringbootmysql.redis.RedisCommons;
import com.example.novelspringbootmysql.service.*;
import com.example.novelspringbootmysql.util.ArticleSpider;
import com.example.novelspringbootmysql.util.JsoupUtil;
import com.example.novelspringbootmysql.vo.BookRackVo;
import com.example.novelspringbootmysql.vo.FictionDetailsVo;
import com.example.novelspringbootmysql.vo.SearchFictionVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.*;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private FictionService fictionService;

    @Autowired
    private TypeService typeService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private ContentService contentService;

    @Autowired
    private AuthorService authorService;

    @Autowired
    private UserService userService;

    @Autowired
    private BookrackService bookrackService;

    @Autowired
    private RedisService redisService;

    @PostMapping("/register")
    public String registerUser(User user) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        // 加密密码
        String encryptedPassword = bCryptPasswordEncoder.encode(user.getPassword());
        user.setPassword(encryptedPassword);

        // 查询userId然后增加1存入
        String userId = userService.selectByMaxId();
        int newUserId = Integer.parseInt(userId)+1;
        user.setUserId(String.valueOf(newUserId));

        // 保存到数据库
        int num = userService.insert(user);
        return "redirect:/user/index";
    }


    @PostMapping("/login")
    public String userLogin(@RequestParam("username") String username,
                            @RequestParam("password") String password,
                            Model model,
                            HttpSession session){
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        User user = userService.findByUsername(username);
        if (user == null){
            model.addAttribute("msg","账号不存在");
            return "redirect:/user/index";
        }
        if (bCryptPasswordEncoder.matches(password,user.getPassword())) {
            model.addAttribute("msg","登录成功");
            session.setAttribute("user",user);
            //查询导航栏书籍类型数据
            List<Type> typeList = typeService.selectAll();
            model.addAttribute("typeList",typeList);
            //查询书籍列表数据
            List<Fiction> fictionList = fictionService.selectAll();
            model.addAttribute("fictionList",fictionList);
            model.addAttribute("typeName","玄幻");
            return "users/index";
        }
        model.addAttribute("msg","密码错误");

        //TODO redis书架榜 优化：只需要查询前10个数据，可以显示加入书架数量
        List<Map.Entry<String, Integer>> rackTopMap = redisService.getKeysMapRackTop();
        //传入map，在service层遍历map，根据fictionId进行查询，返回List<Fiction>
        List<Fiction> rackTopList = new ArrayList<>();
        for (int i = 0; i < rackTopMap.size(); i++) {
            String id = rackTopMap.get(i).getKey();
            String key = id.substring(id.indexOf("_")+1,id.length());
            rackTopList.add(fictionService.selectByFictionId(key));
        }
        model.addAttribute("rackTopList",rackTopList);

        //增加一个功能热搜榜单，查询出redis中的有序集合sorted set的热度最多的前5个榜单
        Set<Object> searchTop = redisService.getZSetOpsReverseRange(RedisCommons.SEARCHKEY,0,4);
        List<Fiction> searchTopList = new ArrayList<>();
        for(Object key : searchTop){
            String newKey = key.toString();
            String finalKey = newKey.substring(newKey.indexOf("_")+1,newKey.length());
            searchTopList.add(fictionService.selectByFictionId(finalKey));
        }
        model.addAttribute("searchTopList",searchTopList);

        return "redirect:/user/index";
    }

    @GetMapping("exit")
    public String exit(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/user/index";
    }

    /**
     * 主页
     * @param model
     * @return
     */
    @GetMapping("/index")
    public String toIndex(Model model) {
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();
        model.addAttribute("typeList",typeList);

        //查询书籍列表数据
        List<Fiction> fictionList = fictionService.selectAll();
        model.addAttribute("fictionList",fictionList);
        model.addAttribute("typeName","全部作品");

        //redis书架榜 优化：只需要查询前10个数据，可以显示加入书架数量
        List<Map.Entry<String, Integer>> rackTopMap = redisService.getKeysMapRackTop();
        //传入map，在service层遍历map，根据fictionId进行查询，返回List<Fiction>
        List<Fiction> rackTopList = new ArrayList<>();
        for (int i = 0; i < rackTopMap.size(); i++) {
            String id = rackTopMap.get(i).getKey();
            String key = id.substring(id.indexOf("_")+1,id.length());
            rackTopList.add(fictionService.selectByFictionId(key));
        }
        model.addAttribute("rackTopList",rackTopList);

        //增加一个功能热搜榜单，查询出redis中的有序集合sorted set的热度最多的前5个榜单
        Set<Object> searchTop = redisService.getZSetOpsReverseRange(RedisCommons.SEARCHKEY,0,4);
        List<Fiction> searchTopList = new ArrayList<>();
        for(Object key : searchTop){
            String newKey = key.toString();
            String finalKey = newKey.substring(newKey.indexOf("_")+1,newKey.length());
            searchTopList.add(fictionService.selectByFictionId(finalKey));
        }
        model.addAttribute("searchTopList",searchTopList);

        return "users/index";
    }

    /**
     * 点击导航栏类型信息查询
     * @param typeId
     * @param typeName
     * @param model
     * @return
     */
    @GetMapping("/toMain")
    public String toXuanHuan(@RequestParam("typeId") String typeId,
                             @RequestParam("typeName") String typeName,
                             Model model) {
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();
        model.addAttribute("typeList",typeList);

        List<Fiction> fictionList;
        if (typeId.equals("0")) {
            //查询全部书籍列表信息
            fictionList = fictionService.selectAll();
        }else {
            //根据类型查询书籍列表信息 findByTypeId(typeId)
            fictionList = fictionService.findByTypeId(typeId);
        }
        model.addAttribute("fictionList",fictionList);
        model.addAttribute("typeName",typeName);
        return "users/bookShow";
    }


    @GetMapping("/toFictionDetails")
    public String toFictionDetails(@RequestParam("fictionId") String fictionId,
                                   @RequestParam("userId") String userId,
                                   Model model){
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();
        model.addAttribute("typeList",typeList);

        //根据fictionId查询fiction信息
        Fiction fiction = fictionService.selectByFictionId(fictionId);
        //根据fiction的authorId查询author信息
        Author author = authorService.selectByAuthorId(fiction.getAuthorId());
        //根据fiction的fictionId查询chapter信息
        List<Chapter> chapter = chapterService.selectByFictionId(fiction.getFictionId());
        //根据fiction的typeId查询type信息
        Type type = typeService.selectByTypeId(fiction.getTypeId());

        FictionDetailsVo fictionDetailsVo = new FictionDetailsVo();
        BeanUtils.copyProperties(fiction,fictionDetailsVo);
        fictionDetailsVo.setTypeName(type.getTypeName());
        fictionDetailsVo.setAuthorName(author.getAuthorName());
        fictionDetailsVo.setAuthorDescription(author.getAuthorDescription());
        fictionDetailsVo.setChapters(chapter);

        int isFictionCount = bookrackService.findBookRackByUserIdOne(userId,fictionId);
        model.addAttribute("fictionDetailsVo",fictionDetailsVo);
        model.addAttribute("isFictionCount",isFictionCount);

        //点击进入书籍详情页，在redis中新增相关的书籍权重新增一个热度点，即权重点
        //这里需要判断，是否存在，Sorted Set中有这个判断
        Double score = redisService.getZSetOpsScore(RedisCommons.SEARCHKEY,RedisCommons.SEARCH+fictionId);
        if (score != null) {
            redisService.setZSetOps(RedisCommons.SEARCHKEY,RedisCommons.SEARCH+fictionId, (int) (score+1));
        }else {
            redisService.setZSetOps(RedisCommons.SEARCHKEY,RedisCommons.SEARCH+fictionId,1);
        }

        return "users/fictionDetails";
    }

    @GetMapping("/toContentsShow")
    public String toContentsShow(@RequestParam("contentId") Long contentId,
                                 @RequestParam("chapterTitle") String chapterTitle,
                                 Model model){
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();
        model.addAttribute("typeList",typeList);

        //根据chapter表的contentId-->id查询content表的contents
        Content content = contentService.selectByPrimaryKey(contentId);
        model.addAttribute("content",content);
        model.addAttribute("chapterTitle",chapterTitle);
        return "users/contentsShow";
    }

    /**
     * 优化：
     * 如果传入的值为空，则需要判断
     * 搜索框中的值需要传入新页面搜索框
     * @param inputText
     * @param model
     * @return
     */
    @GetMapping("/searchFiction")
    public String searchFiction(@RequestParam("inputText") String inputText,Model model){
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();

        //查询书籍列表数据
        List<Fiction> fictionList = fictionService.selectAll();

        List<SearchFictionVo> searchFictionVoList = new ArrayList<>();

        SearchFictionVo searchFictionVo;
        //根据inputText进行模糊查询
        List<Fiction> fictionLikeList = fictionService.selectLikeFictionName(inputText);
        for (Fiction fiction: fictionLikeList) {
            searchFictionVo = new SearchFictionVo();

            //根据fiction的authorId查询author信息
            Author author = authorService.selectByAuthorId(fiction.getAuthorId());
            //根据fiction的typeId查询type信息
            Type type = typeService.selectByTypeId(fiction.getTypeId());
            //根据fiction的fiction_id在chapter表中查询最新章节
            Chapter chapter = chapterService.selectOneByFictionId(fiction.getFictionId());


            //将数据存入vo中
            BeanUtils.copyProperties(fiction,searchFictionVo);
            searchFictionVo.setTypeName(type.getTypeName());
            searchFictionVo.setAuthorName(author.getAuthorName());
            searchFictionVo.setAuthorDescription(author.getAuthorDescription());
            if (chapter != null){
                searchFictionVo.setNewContent(chapter.getChapterTitle());
                searchFictionVo.setContentId(chapter.getContentId());
            }else {
                searchFictionVo.setNewContent(null);
                searchFictionVo.setContentId(null);
            }


            //将vo输入存入集合
            searchFictionVoList.add(searchFictionVo);
        }
        model.addAttribute("inputText",inputText);
        model.addAttribute("typeList",typeList);
        model.addAttribute("fictionList",fictionList);
        model.addAttribute("searchFictionVoList",searchFictionVoList);

        return "users/searchFiction";
    }
    //TODO 在searchFiction.html中，需要多表联合查询，动态sql，ajax

    @GetMapping("/toBookRack")
    public String toBookRack(@RequestParam("userId") String userId,Model model){
        //查询导航栏书籍类型数据
        List<Type> typeList = typeService.selectAll();
        List<BookRackVo> bookRackVoList = bookrackService.findBookRackByUserId(userId);
        model.addAttribute("bookRackVoList",bookRackVoList);
        model.addAttribute("typeList",typeList);
        return "users/bookRack";
    }


    /**
     * 使用爬虫存入数据库目录表chapter，没必要不要调用
     * @return
     */
    @GetMapping("/insertChapter")
    @ResponseBody
    public String insertChapter(){
        //得到小说的目录
        List<String> list = JsoupUtil.inputUrlGetChapter("https://m.bqg337.com/book/25195/list.html");
        //插入表chapter数据
        chapterService.insert(list);
        return "succeed";
    }

    /**
     * 使用爬虫存入数据库内容表content，没必要不要调用
     * @return
     */
    @GetMapping("/insertContent")
    @ResponseBody
    public String insertContent(){
        List<String> urls = ArticleSpider.inputUrlGetAUrl("https://www.23hh.com/book/24/24035/");
        contentService.insert(urls);
        return "succeed";
    }


}
